﻿#ifndef _tcp_client_event_impl_20220427_
#define _tcp_client_event_impl_20220427_

#include <string>
#include <memory>
#include <atomic>
#include <mutex>
#include <SLT_tool_pub.h>

//event id
#define EPOLL_LIST_CMD_ADD_LISTEN_SOCKET        1
#define EPOLL_LIST_CMD_DEL_LISTEN_SOCKET        2
#define EPOLL_LIST_CLIENT_CONNECT                  3  //客户端连接命令
#define EPOLL_LIST_SHUTDOWNFLG                  4
#define EPOLL_LIST_SOCKET_CREATE                   5
#define EPOLL_LIST_SOCKET_DEL                   6
#define EPOLL_LIST_SOCKET_STARTRECV             7
#define EPOLL_LIST_SOCKET_RECVDATAONE           8
#define EPOLL_LIST_SOCKET_CHECKTIMEOUT          9   //检测tcpclient超时
//#define EPOLL_CLINET_CONNECT_SYNCERR            10  //TCP链接同步失败
//
//#define SHUTDOWNFLG                 1

#include "SL_tcpClient.h"

class SLTcpServerEventImpl;
class SLTcpClientEventImpl;
typedef std::shared_ptr<SLTcpClientEventImpl>   SLTcpClientEventImplPtr;
class SLTcpClientEventImpl : public SLTcpClient, public std::enable_shared_from_this<SLTcpClientEventImpl>, public SLT_memLeakCheck<SLTcpClientEventImpl>
{
public:
	struct _tcp_event_info : SLT_EmbedSptrCounterBase< _tcp_event_info>
	{
		int m_cmd = -1;   //EPOLL_LIST_SOCKET_DEL
		SLTcpClientEventImplPtr m_client;
		int m_socket = -1;

		//监听信息
		std::string m_listenip;
		int         m_listenport = 0;
		int         m_result = 0;       //执行结果,0-表示成功，小于0失败
		bool        m_runState = false;  //执行状态，执行是否完成

		//异步连接状态
		int         m_connectState = 0; //0-成功，-1-失败，1-等待   
	};
	typedef SLT_EmbedSmartPtr< _tcp_event_info>  _tcp_event_infoStpr;
    enum tcp_work_state
    {
        tcp_work_state_init,
        tcp_work_state_conning, //连接中
        tcp_work_state_ok
    };
public:
    SLTcpClientEventImpl(uint32_t _id);
    ~SLTcpClientEventImpl();

	virtual void bindCB(SLTcpClientCBPtr _pcb);
    virtual void connect2(std::string _serIp, int _serPort, int _timeout = 5000, std::string _lip = "", int _lport = 0);
    virtual void close2();
    virtual int  send2(const char* _pdata, int _dataLen);
    virtual void recv2();

    virtual void setRecv(bool _enable);
    virtual bool getRecv() { return m_brecv; }
    virtual int  getRecvCount() { return m_recvCount; }

    virtual const slIpAddr& getLocalAddr();
    virtual const slIpAddr& getRemoteAddr();
public:
    std::string toString();
public:
	int  NetConnect(int port, const std::string& host, int timeOut);
	int  initSocket(struct event_base* base, int nsocket);
	void clearEvent();

    //void tcp_cli_writecb_g(void* user_data) { ((SLTcpClientEventImpl*)user_data)->onSend(); }
    //void tcp_cli_readcb_g(void* user_data) { ((SLTcpClientEventImpl*)user_data)->onRecvFromNet(); }
    //void tcp_cli_eventcb_g(short events, void* user_data) { ((SLTcpClientEventImpl*)user_data)->tcp_cli_eventcb(events); }
	void EventProssess(int nSocket, short events);
	int NetWriteSocket(int nSocket, const char* writeBuf, int writeSize,bool _sendcache = false);
    int NetSetNoDelay(int nSocket);
    int NetSetSendTimeo(int nSocket, int _outMs);
    void NetClose(int socket);
    int NetReadSocketOne(int nSocket, char* readBuf, int readSize);

    void _close2();
    static void NoBlock(int fd);

    void onSend2Net();
    void onRecvFromNet();
    int onRecvFromNetInvoke(bool _deccount);

    void onSend();
    void onRecvData(char* _pdata, int _len);
    void onError(tcp_error_type _type);
    SLTcpClientCBPtr m_pcb;

    tcp_work_state   m_workState = tcp_work_state_init;  //被动连接时设置为成功
    int m_lip = 0;  //本地序
    int m_lport = 0;
    slIpAddr m_laddr;
    int m_rip = 0;
    int m_rport = 0;
    slIpAddr m_raddr;

    SLT_memBuf  m_sendBuf;    //发送缓存，一次发送保证全部发送成，again了。就缓存再发送

    int m_socket = -1;
    char m_recvBuf[1024];
    int  m_recvLen = 800;    //每次接收的最大长度,不能和buf 相等。接收时会在末尾补充0
    bool m_brecv = true;    //默认接收，在不接收的情况下，远端关闭事件也没有
    std::atomic<int>   m_recvCount; //在不接受模式下，投递的接收次数

    bool               m_isActive = true;
    SLT_elapseTimer    m_lastActiveTime; //最后活动时间。超过3分钟则回收

    std::mutex  m_socketLock;
    SLTcpServerEventImpl* m_pserver = nullptr;
	struct event* m_general_evwent = nullptr;
    struct event* m_write_event = nullptr;

    uint32_t   m_clientID;

    //static std::atomic<uint32_t>   m_clientBaseID;
};


#endif